package com.gzdh.tang.dishrecognition.job;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzdh.tang.config.ali.AliPayUtil;
import com.gzdh.tang.config.leshua.LeshuaPayUtils;
import com.gzdh.tang.config.weixin.WXEntity;
import com.gzdh.tang.config.weixin.WXPay;
import com.gzdh.tang.config.weixin.WXPayUtils;
import com.gzdh.tang.dishrecognition.service.LsPayService;
import com.gzdh.tang.modu.entity.Addr;
import com.gzdh.tang.modu.entity.MacMainpOrder;
import com.gzdh.tang.modu.entity.MacMainpSbruan;
import com.gzdh.tang.modu.service.MacMainpOrderService;
import com.gzdh.tang.modu.service.MacMainpSbruanService;
import com.gzdh.tang.modu.service.TangAddrService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.Status;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class DrRefundJob {

    @Autowired
    MacMainpOrderService macMainpOrderService;

    @Autowired
    MacMainpSbruanService macMainpSbruanService;

    @Autowired
    TangAddrService tangAddrService;

    @Autowired
    LsPayService lsPayService;

    @XxlJob("DrRefundJobHandler")
    public void DrAliFaceAgreementJobHandler() throws Exception {
        List<MacMainpOrder> macMainpOrders = macMainpOrderService.list(new QueryWrapper<MacMainpOrder>().lambda()
                .in(MacMainpOrder::getOrderType, 1,2,3)
                .eq(MacMainpOrder::getRefundState, 0));
        for (MacMainpOrder goo : macMainpOrders) {
            try {
                switch (goo.getOrderType()) {
                    case 1:
                        wxRequest(goo);
                        break;
                    case 2:
                        aliRequest(goo);
                        break;
                    case 3:
                        lsRequest(goo);
                        break;
                }
            } catch (Exception e){
                log.error("请求报错:{}" + e.toString());
                e.printStackTrace();
            }
        }
    }

    private void wxRequest(MacMainpOrder goo) throws Exception {
        WXEntity wxEntity = new WXEntity();
        WXPay wxPay = new WXPay(wxEntity);
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("out_trade_no", goo.getOrders());
        if (WXPayUtils.getSubmchMode() == 1) {
            reqMap.put("sub_mch_id", WXPayUtils.getSubMchId());
        }
        Map<String, String> resMap = wxPay.orderQuery(reqMap);
        log.info("请求返回结果:{}", resMap);
        if(resMap != null && resMap.get("return_code").equals("SUCCESS") && resMap.get("result_code").equals("SUCCESS")) {
            if(resMap.get("trade_state").equals("REFUND")) { //发生过退款,直接修改标记
                goo.setRefundState(1);
                macMainpOrderService.updateById(goo);
                return;
            }
        }
        Config config = new RSAPublicKeyConfig.Builder()
                .merchantId(WXPayUtils.getMchId())
                .privateKey(WXPayUtils.getPrivateKey())
                .merchantSerialNumber(WXPayUtils.getMerchantSerialNumber())
                .apiV3Key(WXPayUtils.getApiV3Key())
                .publicKey(WXPayUtils.getMerchantPublicKey())
                .publicKeyId(WXPayUtils.getMerchantPublicKeyId())
                .build();
        RefundService service = new RefundService.Builder().config(config).build();
        CreateRequest createRequest = new CreateRequest();

        AmountReq amountReq = new AmountReq();
        amountReq.setRefund(new BigDecimal(goo.getAmountPrice()).multiply(new BigDecimal(100)).stripTrailingZeros().longValue());//【退款金额】 退款金额，单位为分，只能为整数，不能超过原订单支付金额。
        amountReq.setTotal(new BigDecimal(goo.getAmountPrice()).multiply(new BigDecimal(100)).stripTrailingZeros().longValue());//【原订单金额】 原支付交易的订单总金额，单位为分，只能为整数。
        amountReq.setCurrency("CNY");//退款币种】 符合ISO 4217标准的三位字母代码，目前只支持人民币：CNY。
        createRequest.setAmount(amountReq);
        if (WXPayUtils.getSubmchMode() == 1) {
            createRequest.setSubMchid(WXPayUtils.getSubMchId());
        }
        createRequest.setOutTradeNo(goo.getOrders());//【商户订单号】 原支付交易对应的商户订单号，与transaction_id二选一
        createRequest.setOutRefundNo(goo.getRefundOrder());
        Refund refund = service.create(createRequest);
        if (refund.getStatus() == Status.SUCCESS) {
            System.out.println("退款成功");
            goo.setRefundState(1);
        } else if (refund.getStatus() == Status.ABNORMAL || refund.getStatus() == Status.CLOSED) {
            goo.setRefundState(-1);
        }
        goo.setRefundMsg(refund.toString());
        macMainpOrderService.updateById(goo);
    }

    private void aliRequest(MacMainpOrder goo) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                AliPayUtil.getAppid(), AliPayUtil.getPrivateKey(),
                "json", "GBK", AliPayUtil.getPublicKey(),
                "RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setRefundAmount(new BigDecimal(goo.getAmountPrice()).toPlainString());
        model.setOutTradeNo(goo.getOrders());
        model.setOutRequestNo(goo.getRefundOrder());
        request.setBizModel(model);
        try {
            Addr addr = tangAddrService.getOne(new QueryWrapper<Addr>().lambda().eq(Addr::getAddrNo, goo.getAddr()));
            AlipayTradeRefundResponse response = alipayClient.execute(request,null, addr.getAliAppAuthToken());
            if(response.isSuccess()) {
                log.info("支付宝退款成功");
                goo.setRefundState(1);
            } else {
                goo.setRefundState(-1);
            }
            goo.setRefundMsg(response.getSubMsg());
            macMainpOrderService.updateById(goo);
        } catch (AlipayApiException e) {
            throw new Exception("alipay.trade.refund退款接口：订单签名错误");
        }
    }

    private void lsRequest(MacMainpOrder goo) throws Exception {
        try {
            String merchantId;
            String key;
            if (LeshuaPayUtils.getUseDatabaseConfig()) {
                //使用乐刷数据库配置
                MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().eq("pos", goo.getPosNum()));
                if(macMainpSbruan == null) {
                    throw new RuntimeException("找不到与机号匹配的设备信息");
                }
                Map<String, Object> payConfigMap = macMainpSbruanService.getCanteenPayConfig(macMainpSbruan.getLsCanteenPayId());
                if(payConfigMap == null) {
                    throw new RuntimeException("支付参数获取失败");
                }
                merchantId = String.valueOf(payConfigMap.get("mchId")).trim();
                key = String.valueOf(payConfigMap.get("key")).trim();
            } else {
                merchantId = LeshuaPayUtils.getMerchantId();
                key = LeshuaPayUtils.getKey();
            }
            String refundAmount = new BigDecimal(goo.getAmountPrice()).multiply(new BigDecimal(100)).toPlainString();
            Map<String, String> resMap = lsPayService.lsRefund(goo.getOrders(), goo.getRefundOrder(), refundAmount, merchantId, key);
            if (!"0".equals(resMap.get("resp_code"))) {
                log.error(goo.getOrders() + "DrRefundJob:退款失败===>" + resMap.get("resp_msg"));
                throw new RuntimeException(resMap.get("resp_msg"));
            }
            if (!"0".equals(resMap.get("result_code"))) {
                log.error(goo.getOrders() + "DrRefundJob:退款失败===>" + resMap.get("error_msg"));
                throw new RuntimeException(resMap.get("error_msg"));
            }
            if("10".equals(resMap.get("status"))) {
                goo.setRefundState(1);
            } else {
                goo.setRefundState(-1);
            }
            goo.setRefundMsg(resMap.get("failure_reason"));
            macMainpOrderService.updateById(goo);
        } catch (Exception e) {
            log.error(e.toString());
            throw new Exception(e.getMessage());
        }
    }
}
